﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DataVisualization
{
    public partial class GroceryVisualizer : Form
    {
        DataGridView dataSet;
        List<long> numUniqueItemsInColumn;
        List<List<string>> uniqueItemsInColumn;
        List<List<bool>> labelAdded;
        string currentClick;
        public GroceryVisualizer()
        {
            InitializeComponent();
            dataSet = new DataGridView();
            numUniqueItemsInColumn = new List<long>();
            uniqueItemsInColumn = new List<List<string>>();
            labelAdded = new List<List<bool>>();
        }

        public GroceryVisualizer(DataGridView infoSet)
        {
            InitializeComponent();
            SetStyle(ControlStyles.UserPaint, true); //not entirely sure what this does, but does improve flickering a little
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); //prevents whole image flickers
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true); //prevents flickering of images on top of other images
            dataSet = infoSet;
            numUniqueItemsInColumn = new List<long>();
            uniqueItemsInColumn = new List<List<string>>();
            labelAdded = new List<List<bool>>();
            identifyUniqueItems();
        }

        private void GroceryVisualizer_Paint(object sender, PaintEventArgs e)
        {
            float width = this.Width - 40;
            float height = this.Height - 40;
            /*
            PointF upperLeft = new PointF(-width/2, height/2);
            PointF leftCenter = new PointF(-width/2, 0);
            PointF rightCenter = new PointF(width/2, 0);
            PointF upperCenter = new PointF(0, height/2);
            PointF lowerCenter = new PointF(0, -height/2);
            PointF upperRight = new PointF(width/2, height/2);
            PointF lowerRight = new PointF(width/2, -height/2);
            PointF lowerLeft = new PointF(-width/2, -height/2);
            PointF centerPoint = new PointF(0, 0);
            */
            PointF upperLeft = new PointF(0, 0);
            PointF leftCenter = new PointF(0, height/2);
            PointF rightCenter = new PointF(width, height/2);
            PointF upperCenter = new PointF(width/2, 0);
            PointF lowerCenter = new PointF(width/2, height);
            PointF upperRight = new PointF(width, 0);
            PointF lowerRight = new PointF(width, height);
            PointF lowerLeft = new PointF(0, height);
            PointF centerPoint = new PointF(width/2, height/2);
            Graphics g = e.Graphics;
            //g.TranslateTransform(width / 2, height / 2);
            Pen p = new Pen(Color.Green);
            g.DrawLine(p, upperRight, lowerLeft);
            g.DrawLine(p, upperLeft, lowerRight);
            g.DrawLine(p, upperCenter, lowerCenter);
            g.DrawLine(p, leftCenter, rightCenter);
            try
            {
                
                for (int i = 0; i < dataSet.RowCount - 1; ++i)
                {
                    Pen r;
                    if (currentClick != null)
                    {
                        
                        r = new Pen(Color.Transparent);
                    }
                    else
                    {
                        r = new Pen(Color.White); //r = new Pen(Color.Transparent);
                    }
                    p = new Pen(Color.Red);
                    List<PointF> polygon = new List<PointF>();
                    for (int j = 0; j < dataSet.ColumnCount; ++j)
                    {
                        //dataSet.CurrentCell = dataSet[j, i];
                        string cellString = dataSet.Rows[i].Cells[j].Value.ToString();//dataSet.CurrentCell.Value.ToString();
                        //Console.WriteLine(cellString);
                        if (j == 0)
                        {
                            cellString = getAge(cellString);
                        }
                        else if (j == 2)
                        {
                            cellString = getIncome(cellString);
                        }
                        else if (j == 3)
                        {
                            cellString = getSpent(cellString);
                        }
                        float currentDiv = uniqueItemsInColumn[j].IndexOf(cellString);
                        currentDiv++;
                        if (cellString == currentClick)
                        {
                            r.Color = Color.Purple;
                        }
                        //make switch eventually and make changable
                        if (j == 0)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, lowerCenter, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush,calculatedPoint);
                        }
                        else if (j == 1)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, upperLeft, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush,calculatedPoint);
                        }
                        else if (j == 2)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, upperCenter, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                        }
                        else if (j == 3)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, rightCenter, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                        }
                        else if (j == 4)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, upperRight, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                        }
                        else if (j == 5)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, lowerRight, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.AutoSize = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                        }
                        else if (j == 6)
                        {
                            PointF calculatedPoint = divideLine(centerPoint, leftCenter, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (currentDiv % 2 == 0)
                            {
                                if (!labelAdded[j][(int)currentDiv - 1])
                                {
                                    labelAdded[j][(int)currentDiv - 1] = true;
                                    Label lblControl = new Label();
                                    lblControl.Text = cellString;
                                    lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                    lblControl.Visible = true;
                                    lblControl.AutoSize = true;
                                    lblControl.BackColor = Color.Transparent;
                                    lblControl.Click += new EventHandler(lbl_Click);
                                    Controls.Add(lblControl);
                                }
                                //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                            }
                            else
                            {
                                calculatedPoint.Y -= 20;
                                if (!labelAdded[j][(int)currentDiv - 1])
                                {
                                    labelAdded[j][(int)currentDiv - 1] = true;
                                    Label lblControl = new Label();
                                    lblControl.Text = cellString;
                                    lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                    lblControl.Visible = true;
                                    lblControl.BackColor = Color.Transparent;
                                    lblControl.AutoSize = true;
                                    lblControl.Click += new EventHandler(lbl_Click);
                                    Controls.Add(lblControl);
                                }
                                //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                            }
                        }
                        else
                        {
                            PointF calculatedPoint = divideLine(centerPoint, lowerLeft, currentDiv / numUniqueItemsInColumn[j]);
                            polygon.Add(calculatedPoint);
                            if (!labelAdded[j][(int)currentDiv - 1])
                            {
                                labelAdded[j][(int)currentDiv - 1] = true;
                                Label lblControl = new Label();
                                lblControl.Text = cellString;
                                lblControl.Location = new Point((int)calculatedPoint.X, (int)calculatedPoint.Y);
                                lblControl.Visible = true;
                                lblControl.BackColor = Color.Transparent;
                                lblControl.AutoSize = true;
                                lblControl.Click += new EventHandler(lbl_Click);
                                Controls.Add(lblControl);
                            }
                            //g.DrawString(cellString, new Font("Arial", 8), p.Brush, calculatedPoint);
                        }
                    }
                    List<PointF> sortedList = new List<PointF>();

                    //Not needed, was a test for something else but it stuck
                    sortedList.Add(polygon[0]); //0
                    sortedList.Add(polygon[7]); //1
                    sortedList.Add(polygon[6]); //2
                    sortedList.Add(polygon[1]); //3
                    sortedList.Add(polygon[2]); //4
                    sortedList.Add(polygon[4]); //5
                    sortedList.Add(polygon[3]); //6
                    sortedList.Add(polygon[5]); //7

                    g.DrawPolygon(r, sortedList.ToArray());
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private PointF divideLine(PointF pointA, PointF pointB, float divisor)
        {
            //(x,y) = (x1 + k (x2 – x1), y1 + k (y2 – y1))
            PointF newpoint = new PointF((pointB.X + divisor * (pointA.X - pointB.X)), (pointB.Y + divisor*(pointA.Y - pointB.Y)));
            //Console.WriteLine("Point A = " + pointA.ToString() + " Point B = " + pointB.ToString() + " with a divisor of " + divisor.ToString() + " Co-ordinate of " + newpoint.ToString());
            return newpoint;
        }

        private string getAge(string cellString)
        {
            int age;
            age = int.Parse(cellString);
            if (age < 30)
            {
                cellString = "20's";
            }
            else if (age < 40)
            {
                cellString = "30's";
            }
            else if (age < 50)
            {
                cellString = "40's";
            }
            else if (age < 60)
            {
                cellString = "50's";
            }
            else if (age < 70)
            {
                cellString = "60's";
            }
            else
            {
                cellString = "Old";
            }
            return cellString;
        }
        private string getIncome(string cellString)
        {
            Int64 income;
            income = Int64.Parse(cellString);
            if (income < 10000)
            {
                cellString = "Less than $10,000";
            }
            else if (income < 20000)
            {
                cellString = "$10,000";
            }
            else if (income < 30000)
            {
                cellString = "$20,000";
            }
            else if (income < 40000)
            {
                cellString = "$40,000";
            }
            else if (income < 50000)
            {
                cellString = "$60,000";
            }
            else if (income < 60000)
            {
                cellString = "$50,000";
            }
            else if (income < 70000)
            {
                cellString = "$60,000";
            }
            else if (income < 80000)
            {
                cellString = "$70,000";
            }
            else if (income < 90000)
            {
                cellString = "$80,000";
            }
            else if (income < 100000)
            {
                cellString = "$90,000";
            }
            else
            {
                cellString = "Over $100,000";
            }
            return cellString;
        }

        private string getSpent(string cellString)
        {
            double spent;
            spent = Double.Parse(cellString);
            if (spent == 0)
            {
                cellString = "Nothing";
            }
            else if (spent < 100)
            {
                cellString = "Less than $100";
            }
            else if (spent < 200)
            {
                cellString = "$100's";
            }
            else if (spent < 300)
            {
                cellString = "$200's";
            }
            else
            {
                cellString = "Over $200's";
            }
            return cellString;
        }

        private void identifyUniqueItems()
        {
            for (int i = 0; i < dataSet.Columns.Count; ++i)
            {
                uniqueItemsInColumn.Add(new List<string>());
                labelAdded.Add(new List<bool>());
                numUniqueItemsInColumn.Add(1);
                foreach (DataGridViewRow row in dataSet.Rows)
                {
                    string cellString = (string)row.Cells[i].Value;
                    if (cellString != null)
                    {
                        if (i == 0)
                        {
                            cellString = getAge(cellString);
                        }
                        else if (i == 2)
                        {
                            cellString = getIncome(cellString);
                        }
                        else if (i == 3)
                        {
                            cellString = getSpent(cellString);
                        }
                        if (!uniqueItemsInColumn[i].Contains(cellString))
                        {
                            numUniqueItemsInColumn[i]++;
                            uniqueItemsInColumn[i].Add(cellString);
                            labelAdded[i].Add(false);
                            //Console.WriteLine(numUniqueItemsInColumn[i].ToString());
                        }
                    }
                }
            }
        }

        private void lbl_Click(object sender, EventArgs e)
        {
            Control ctrl = (Control)sender;
            currentClick = ctrl.Text;
            Console.WriteLine(currentClick);
            this.Invalidate();
        }

        private void GroceryVisualizer_Resize(object sender, EventArgs e)
        {
            this.Controls.Clear();
            for (int i = 0; i < labelAdded.Count; ++i)
            {
                for (int j = 0; j < labelAdded[i].Count; ++j)
                {
                    labelAdded[i][j] = false;
                }
            }
            this.Invalidate();
        }
    }
}
